home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / BNU22SR1.ZIP / src / binutils.2 / gprof / printgpr.c < prev    next >
C/C++ Source or Header  |  1993-05-30  |  21KB  |  790 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that: (1) source distributions retain this entire copyright
  7.  * notice and comment, and (2) distributions including binaries display
  8.  * the following acknowledgement:  ``This product includes software
  9.  * developed by the University of California, Berkeley and its contributors''
  10.  * in the documentation or other materials provided with the distribution
  11.  * and in all advertising materials mentioning features or use of this
  12.  * software. Neither the name of the University nor the names of its
  13.  * contributors may be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)printgprof.c    5.7 (Berkeley) 6/1/90";
  22. #endif /* not lint */
  23.  
  24. #include "gprof.h"
  25. #include <demangle.h>
  26.  
  27. printprof()
  28. {
  29.     register nltype    *np;
  30.     nltype        **sortednlp;
  31.     int            index, timecmp();
  32.  
  33.     actime = 0.0;
  34.     if ( bsd_style_output ) {
  35.     printf( "\f\n" );
  36.     if ( bflag) {
  37.         printf( "\n\n\nflat profile:\n" );
  38.         flat_blurb(stdout);
  39.     }
  40.     }
  41.     else
  42.     printf ("Flat profile:\n");
  43.     flatprofheader();
  44.     /*
  45.      *    Sort the symbol table in by time
  46.      */
  47.     sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
  48.     if ( sortednlp == (nltype **) 0 ) {
  49.     fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
  50.     }
  51.     for ( index = 0 ; index < nname ; index += 1 ) {
  52.     sortednlp[ index ] = &nl[ index ];
  53.     }
  54.     qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
  55.     for ( index = 0 ; index < nname ; index += 1 ) {
  56.     np = sortednlp[ index ];
  57.     flatprofline( np );
  58.     }
  59.     actime = 0.0;
  60.     cfree( sortednlp );
  61.     if ( bflag && !bsd_style_output ) {
  62.     flat_blurb(stdout);
  63.     }
  64. }
  65.  
  66. timecmp( npp1 , npp2 )
  67.     nltype **npp1, **npp2;
  68. {
  69.     double    timediff;
  70.     long    calldiff;
  71.  
  72.     timediff = (*npp2) -> time - (*npp1) -> time;
  73.     if ( timediff > 0.0 )
  74.     return 1 ;
  75.     if ( timediff < 0.0 )
  76.     return -1;
  77.     calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
  78.     if ( calldiff > 0 )
  79.     return 1;
  80.     if ( calldiff < 0 )
  81.     return -1;
  82.     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
  83. }
  84.  
  85.     /*
  86.      *    header for flatprofline
  87.      */
  88. flatprofheader()
  89. {
  90.     
  91.     if (bsd_style_output) {
  92.     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
  93.            (long) scale * sizeof(UNIT) );
  94.     if ( totime > 0.0 ) {
  95.         printf( " for %.2f%% of %.2f seconds\n\n" ,
  96.            100.0/totime , totime / hz );
  97.     } else {
  98.         printf( " no time accumulated\n\n" );
  99.         /*
  100.          *    this doesn't hurt since all the numerators will be zero.
  101.          */
  102.         totime = 1.0;
  103.     }
  104.     }
  105.     else {
  106.     printf( "\nEach sample counts as %g seconds.\n",
  107.            1.0 / hz);
  108.     }
  109.     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
  110.         "%  " , "cumulative" , "self  " , "" , "self  " , "total " , "" );
  111.     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
  112.         "time" , "seconds " , "seconds" , "calls" ,
  113.         "ms/call" , "ms/call" , "name" );
  114. }
  115.  
  116. flatprofline( np )
  117.     register nltype    *np;
  118. {
  119.  
  120.     if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
  121.     return;
  122.     }
  123.     actime += np -> time;
  124.     if (bsd_style_output)
  125.     printf( "%5.1f %10.2f %8.2f" ,
  126.            100 * np -> time / totime , actime / hz , np -> time / hz );
  127.     else
  128.     printf( "%6.2f %9.2f %8.2f" ,
  129.            100 * np -> time / totime , actime / hz , np -> time / hz );
  130.     if ( np -> ncall != 0 ) {
  131.     printf( " %8d %8.2f %8.2f  " , np -> ncall ,
  132.         1000 * np -> time / hz / np -> ncall ,
  133.         1000 * ( np -> time + np -> childtime ) / hz / np -> ncall );
  134.     } else {
  135.     printf( " %8.8s %8.8s %8.8s  " , "" , "" , "" );
  136.     }
  137.     if (bsd_style_output)
  138.     printname( np );
  139.     else
  140.     printnameonly( np );
  141.     printf( "\n" );
  142. }
  143.  
  144. gprofheader()
  145. {
  146.  
  147.     if (!bsd_style_output)
  148.     if (bflag)
  149.         printf ("\t\t     Call graph (explanation follows)\n\n");
  150.     else
  151.         printf ("\t\t\tCall graph\n\n");
  152.     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
  153.         (long) scale * sizeof(UNIT) );
  154.     if ( printtime > 0.0 ) {
  155.     printf( " for %.2f%% of %.2f seconds\n\n" ,
  156.         100.0/printtime , printtime / hz );
  157.     } else {
  158.     printf( " no time propagated\n\n" );
  159.         /*
  160.          *    this doesn't hurt, since all the numerators will be 0.0
  161.          */
  162.     printtime = 1.0;
  163.     }
  164.     if (bsd_style_output) {
  165.     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
  166.            "" , "" , "" , "" , "called" , "total" , "parents");
  167.     printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
  168.            "index" , "%time" , "self" , "descendents" ,
  169.            "called" , "self" , "name" , "index" );
  170.     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
  171.            "" , "" , "" , "" , "called" , "total" , "children");
  172.     printf( "\n" );
  173.     } else {
  174.     printf( "index %% time    self  children    called     name\n" );
  175.     }
  176. }
  177.  
  178. gprofline( np )
  179.     register nltype    *np;
  180. {
  181.     char    kirkbuffer[ BUFSIZ ];
  182.  
  183.     sprintf( kirkbuffer , "[%d]" , np -> index );
  184.     printf(bsd_style_output
  185.        ? "%-6.6s %5.1f %7.2f %11.2f"
  186.        : "%-6.6s %5.1f %7.2f %7.2f" ,
  187.        kirkbuffer ,
  188.        100 * ( np -> propself + np -> propchild ) / printtime ,
  189.        np -> propself / hz ,
  190.        np -> propchild / hz );
  191.     if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
  192.     printf( " %7d" , np -> ncall );
  193.     if ( np -> selfcalls != 0 ) {
  194.         printf( "+%-7d " , np -> selfcalls );
  195.     } else {
  196.         printf( " %7.7s " , "" );
  197.     }
  198.     } else {
  199.     printf( " %7.7s %7.7s " , "" , "" );
  200.     }
  201.     printname( np );
  202.     printf( "\n" );
  203. }
  204.  
  205. printgprof(timesortnlp)
  206.     nltype    **timesortnlp;
  207. {
  208.     int        index;
  209.     nltype    *parentp;
  210.  
  211.     /*
  212.      *    Print out the structured profiling list
  213.      */
  214.     if ( bflag && bsd_style_output ) {
  215.     bsd_callg_blurb(stdout);
  216.     }
  217.     gprofheader();
  218.     for ( index = 0 ; index < nname + ncycle ; index ++ ) {
  219.     parentp = timesortnlp[ index ];
  220.     if ( zflag == 0 &&
  221.          parentp -> ncall == 0 &&
  222.          parentp -> selfcalls == 0 &&
  223.          parentp -> propself == 0 &&
  224.          parentp -> propchild == 0 ) {
  225.         continue;
  226.     }
  227.     if ( ! parentp -> printflag ) {
  228.         continue;
  229.     }
  230.     if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
  231.         /*
  232.          *    cycle header
  233.          */
  234.         printcycle( parentp );
  235.         printmembers( parentp );
  236.     } else {
  237.         printparents( parentp );
  238.         gprofline( parentp );
  239.         printchildren( parentp );
  240.     }
  241.     if (bsd_style_output)
  242.         printf( "\n" );
  243.     printf( "-----------------------------------------------\n" );
  244.     if (bsd_style_output)
  245.         printf( "\n" );
  246.     }
  247.     cfree( timesortnlp );
  248.     if ( bflag && !bsd_style_output) {
  249.     fsf_callg_blurb(stdout);
  250.     }
  251. }
  252.  
  253.     /*
  254.      *    sort by decreasing propagated time
  255.      *    if times are equal, but one is a cycle header,
  256.      *        say that's first (e.g. less, i.e. -1).
  257.      *    if one's name doesn't have an underscore and the other does,
  258.      *        say the one is first.
  259.      *    all else being equal, sort by names.
  260.      */
  261. int
  262. totalcmp( npp1 , npp2 )
  263.     nltype    **npp1;
  264.     nltype    **npp2;
  265. {
  266.     register nltype    *np1 = *npp1;
  267.     register nltype    *np2 = *npp2;
  268.     double        diff;
  269.  
  270.     diff =    ( np1 -> propself + np1 -> propchild )
  271.         - ( np2 -> propself + np2 -> propchild );
  272.     if ( diff < 0.0 )
  273.         return 1;
  274.     if ( diff > 0.0 )
  275.         return -1;
  276.     if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 
  277.     return -1;
  278.     if ( np2 -> name == 0 && np2 -> cycleno != 0 )
  279.     return 1;
  280.     if ( np1 -> name == 0 )
  281.     return -1;
  282.     if ( np2 -> name == 0 )
  283.     return 1;
  284.     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
  285.     return -1;
  286.     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
  287.     return 1;
  288.     if ( np1 -> ncall > np2 -> ncall )
  289.     return -1;
  290.     if ( np1 -> ncall < np2 -> ncall ) 
  291.     return 1;
  292.     return strcmp( np1 -> name , np2 -> name );
  293. }
  294.  
  295. printparents( childp )
  296.     nltype    *childp;
  297. {
  298.     nltype    *parentp;
  299.     arctype    *arcp;
  300.     nltype    *cycleheadp;
  301.  
  302.     if ( childp -> cyclehead != 0 ) {
  303.     cycleheadp = childp -> cyclehead;
  304.     } else {
  305.     cycleheadp = childp;
  306.     }
  307.     if ( childp -> parents == 0 ) {
  308.     printf(bsd_style_output 
  309.            ? "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n"
  310.            : "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s     <spontaneous>\n" ,
  311.         "" , "" , "" , "" , "" , "" );
  312.     return;
  313.     }
  314.     sortparents( childp );
  315.     for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
  316.     parentp = arcp -> arc_parentp;
  317.     if ( childp == parentp ||
  318.          ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
  319.         /*
  320.          *    selfcall or call among siblings
  321.          */
  322.         printf(bsd_style_output
  323.            ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     "
  324.            : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s     " ,
  325.             "" , "" , "" , "" ,
  326.             arcp -> arc_count , "" );
  327.         printname( parentp );
  328.         printf( "\n" );
  329.     } else {
  330.         /*
  331.          *    regular parent of child
  332.          */
  333.         printf(bsd_style_output
  334.            ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     "
  335.            : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d     ",
  336.             "" , "" ,
  337.             arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
  338.             arcp -> arc_count , cycleheadp -> ncall );
  339.         printname( parentp );
  340.         printf( "\n" );
  341.     }
  342.     }
  343. }
  344.  
  345. printchildren( parentp )
  346.     nltype    *parentp;
  347. {
  348.     nltype    *childp;
  349.     arctype    *arcp;
  350.  
  351.     sortchildren( parentp );
  352.     arcp = parentp -> children;
  353.     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
  354.     childp = arcp -> arc_childp;
  355.     if ( childp == parentp ||
  356.         ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
  357.         /*
  358.          *    self call or call to sibling
  359.          */
  360.         printf(bsd_style_output
  361.            ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     "
  362.            : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s     " ,
  363.            "" , "" , "" , "" , arcp -> arc_count , "" );
  364.         printname( childp );
  365.         printf( "\n" );
  366.     } else {
  367.         /*
  368.          *    regular child of parent
  369.          */
  370.         printf(bsd_style_output
  371.            ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     "
  372.            : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d     " ,
  373.            "" , "" ,
  374.            arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
  375.            arcp -> arc_count , childp -> cyclehead -> ncall );
  376.         printname( childp );
  377.         printf( "\n" );
  378.     }
  379.     }
  380. }
  381.  
  382. /* Print name of symbol.  Return number of characters printed. */
  383.  
  384. int
  385. printnameonly ( selfp )
  386.     nltype    *selfp;
  387. {
  388.     int size = 0;
  389.     CONST char *name = selfp->name;
  390.     if (name != NULL) {
  391.     char *demangled = NULL;
  392.     if (!bsd_style_output) {
  393.         if (name[0] == '_' && name[1] && discard_underscores)
  394.         name++;
  395.         demangled = cplus_demangle (name, DMGL_ANSI|DMGL_PARAMS);
  396.         if (demangled)
  397.         name = demangled;
  398.     }
  399.     printf( "%s" , name );
  400.     size = strlen (name);
  401.     if (demangled)
  402.         free (demangled);
  403. #ifdef DEBUG
  404.     if ( debug & DFNDEBUG ) {
  405.         printf( "{%d} " , selfp -> toporder );
  406.     }
  407.     if ( debug & PROPDEBUG ) {
  408.         printf( "%5.2f%% " , selfp -> propfraction );
  409.     }
  410. #endif DEBUG
  411.     }
  412.     return size;
  413. }
  414.  
  415. printname( selfp )
  416.     nltype    *selfp;
  417. {
  418.     printnameonly (selfp);
  419.  
  420.     if ( selfp -> cycleno != 0 ) {
  421.     printf( " <cycle %d>" , selfp -> cycleno );
  422.     }
  423.     if ( selfp -> index != 0 ) {
  424.     if ( selfp -> printflag ) {
  425.         printf( " [%d]" , selfp -> index );
  426.     } else {
  427.         printf( " (%d)" , selfp -> index );
  428.     }
  429.     }
  430. }
  431.  
  432. sortchildren( parentp )
  433.     nltype    *parentp;
  434. {
  435.     arctype    *arcp;
  436.     arctype    *detachedp;
  437.     arctype    sorted;
  438.     arctype    *prevp;
  439.  
  440.     /*
  441.      *    unlink children from parent,
  442.      *    then insertion sort back on to sorted's children.
  443.      *        *arcp    the arc you have detached and are inserting.
  444.      *        *detachedp    the rest of the arcs to be sorted.
  445.      *        sorted    arc list onto which you insertion sort.
  446.      *        *prevp    arc before the arc you are comparing.
  447.      */
  448.     sorted.arc_childlist = 0;
  449.     for (  (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist);
  450.         arcp ;
  451.        (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) {
  452.         /*
  453.          *    consider *arcp as disconnected
  454.          *    insert it into sorted
  455.          */
  456.     for (   prevp = &sorted ;
  457.         prevp -> arc_childlist ;
  458.         prevp = prevp -> arc_childlist ) {
  459.         if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
  460.         break;
  461.         }
  462.     }
  463.     arcp -> arc_childlist = prevp -> arc_childlist;
  464.     prevp -> arc_childlist = arcp;
  465.     }
  466.     /*
  467.      *    reattach sorted children to parent
  468.      */
  469.     parentp -> children = sorted.arc_childlist;
  470. }
  471.  
  472. sortparents( childp )
  473.     nltype    *childp;
  474. {
  475.     arctype    *arcp;
  476.     arctype    *detachedp;
  477.     arctype    sorted;
  478.     arctype    *prevp;
  479.  
  480.     /*
  481.      *    unlink parents from child,
  482.      *    then insertion sort back on to sorted's parents.
  483.      *        *arcp    the arc you have detached and are inserting.
  484.      *        *detachedp    the rest of the arcs to be sorted.
  485.      *        sorted    arc list onto which you insertion sort.
  486.      *        *prevp    arc before the arc you are comparing.
  487.      */
  488.     sorted.arc_parentlist = 0;
  489.     for (  (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist);
  490.         arcp ;
  491.        (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) {
  492.         /*
  493.          *    consider *arcp as disconnected
  494.          *    insert it into sorted
  495.          */
  496.     for (   prevp = &sorted ;
  497.         prevp -> arc_parentlist ;
  498.         prevp = prevp -> arc_parentlist ) {
  499.         if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
  500.         break;
  501.         }
  502.     }
  503.     arcp -> arc_parentlist = prevp -> arc_parentlist;
  504.     prevp -> arc_parentlist = arcp;
  505.     }
  506.     /*
  507.      *    reattach sorted arcs to child
  508.      */
  509.     childp -> parents = sorted.arc_parentlist;
  510. }
  511.  
  512.     /*
  513.      *    print a cycle header
  514.      */
  515. printcycle( cyclep )
  516.     nltype    *cyclep;
  517. {
  518.     char    kirkbuffer[ BUFSIZ ];
  519.  
  520.     sprintf( kirkbuffer , "[%d]" , cyclep -> index );
  521.     printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
  522.         kirkbuffer ,
  523.         100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
  524.         cyclep -> propself / hz ,
  525.         cyclep -> propchild / hz ,
  526.         cyclep -> ncall );
  527.     if ( cyclep -> selfcalls != 0 ) {
  528.     printf( "+%-7d" , cyclep -> selfcalls );
  529.     } else {
  530.     printf( " %7.7s" , "" );
  531.     }
  532.     printf( " <cycle %d as a whole>\t[%d]\n" ,
  533.         cyclep -> cycleno , cyclep -> index );
  534. }
  535.  
  536.     /*
  537.      *    print the members of a cycle
  538.      */
  539. printmembers( cyclep )
  540.     nltype    *cyclep;
  541. {
  542.     nltype    *memberp;
  543.  
  544.     sortmembers( cyclep );
  545.     for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
  546.     printf( "%6.6s %5.5s %7.2f %11.2f %7d" , 
  547.         "" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
  548.         memberp -> ncall );
  549.     if ( memberp -> selfcalls != 0 ) {
  550.         printf( "+%-7d" , memberp -> selfcalls );
  551.     } else {
  552.         printf( " %7.7s" , "" );
  553.     }
  554.     printf( "     " );
  555.     printname( memberp );
  556.     printf( "\n" );
  557.     }
  558. }
  559.  
  560.     /*
  561.      *    sort members of a cycle
  562.      */
  563. sortmembers( cyclep )
  564.     nltype    *cyclep;
  565. {
  566.     nltype    *todo;
  567.     nltype    *doing;
  568.     nltype    *prev;
  569.  
  570.     /*
  571.      *    detach cycle members from cyclehead,
  572.      *    and insertion sort them back on.
  573.      */
  574.     todo = cyclep -> cnext;
  575.     cyclep -> cnext = 0;
  576.     for (  (doing = todo)&&(todo = doing -> cnext);
  577.         doing ;
  578.        (doing = todo )&&(todo = doing -> cnext )){
  579.     for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
  580.         if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
  581.         break;
  582.         }
  583.     }
  584.     doing -> cnext = prev -> cnext;
  585.     prev -> cnext = doing;
  586.     }
  587. }
  588.  
  589.     /*
  590.      *    major sort is on propself + propchild,
  591.      *    next is sort on ncalls + selfcalls.
  592.      */
  593. int
  594. membercmp( this , that )
  595.     nltype    *this;
  596.     nltype    *that;
  597. {
  598.     double    thistime = this -> propself + this -> propchild;
  599.     double    thattime = that -> propself + that -> propchild;
  600.     long    thiscalls = this -> ncall + this -> selfcalls;
  601.     long    thatcalls = that -> ncall + that -> selfcalls;
  602.  
  603.     if ( thistime > thattime ) {
  604.     return GREATERTHAN;
  605.     }
  606.     if ( thistime < thattime ) {
  607.     return LESSTHAN;
  608.     }
  609.     if ( thiscalls > thatcalls ) {
  610.     return GREATERTHAN;
  611.     }
  612.     if ( thiscalls < thatcalls ) {
  613.     return LESSTHAN;
  614.     }
  615.     return EQUALTO;
  616. }
  617.     /*
  618.      *    compare two arcs to/from the same child/parent.
  619.      *    - if one arc is a self arc, it's least.
  620.      *    - if one arc is within a cycle, it's less than.
  621.      *    - if both arcs are within a cycle, compare arc counts.
  622.      *    - if neither arc is within a cycle, compare with
  623.      *        arc_time + arc_childtime as major key
  624.      *        arc count as minor key
  625.      */
  626. int
  627. arccmp( thisp , thatp )
  628.     arctype    *thisp;
  629.     arctype    *thatp;
  630. {
  631.     nltype    *thisparentp = thisp -> arc_parentp;
  632.     nltype    *thischildp = thisp -> arc_childp;
  633.     nltype    *thatparentp = thatp -> arc_parentp;
  634.     nltype    *thatchildp = thatp -> arc_childp;
  635.     double    thistime;
  636.     double    thattime;
  637.  
  638. #   ifdef DEBUG
  639.     if ( debug & TIMEDEBUG ) {
  640.         printf( "[arccmp] " );
  641.         printname( thisparentp );
  642.         printf( " calls " );
  643.         printname ( thischildp );
  644.         printf( " %f + %f %d/%d\n" ,
  645.             thisp -> arc_time , thisp -> arc_childtime ,
  646.             thisp -> arc_count , thischildp -> ncall );
  647.         printf( "[arccmp] " );
  648.         printname( thatparentp );
  649.         printf( " calls " );
  650.         printname( thatchildp );
  651.         printf( " %f + %f %d/%d\n" ,
  652.             thatp -> arc_time , thatp -> arc_childtime ,
  653.             thatp -> arc_count , thatchildp -> ncall );
  654.         printf( "\n" );
  655.     }
  656. #   endif DEBUG
  657.     if ( thisparentp == thischildp ) {
  658.         /* this is a self call */
  659.     return LESSTHAN;
  660.     }
  661.     if ( thatparentp == thatchildp ) {
  662.         /* that is a self call */
  663.     return GREATERTHAN;
  664.     }
  665.     if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
  666.     thisparentp -> cycleno == thischildp -> cycleno ) {
  667.         /* this is a call within a cycle */
  668.     if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
  669.         thatparentp -> cycleno == thatchildp -> cycleno ) {
  670.         /* that is a call within the cycle, too */
  671.         if ( thisp -> arc_count < thatp -> arc_count ) {
  672.         return LESSTHAN;
  673.         }
  674.         if ( thisp -> arc_count > thatp -> arc_count ) {
  675.         return GREATERTHAN;
  676.         }
  677.         return EQUALTO;
  678.     } else {
  679.         /* that isn't a call within the cycle */
  680.         return LESSTHAN;
  681.     }
  682.     } else {
  683.         /* this isn't a call within a cycle */
  684.     if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
  685.         thatparentp -> cycleno == thatchildp -> cycleno ) {
  686.         /* that is a call within a cycle */
  687.         return GREATERTHAN;
  688.     } else {
  689.         /* neither is a call within a cycle */
  690.         thistime = thisp -> arc_time + thisp -> arc_childtime;
  691.         thattime = thatp -> arc_time + thatp -> arc_childtime;
  692.         if ( thistime < thattime )
  693.         return LESSTHAN;
  694.         if ( thistime > thattime )
  695.         return GREATERTHAN;
  696.         if ( thisp -> arc_count < thatp -> arc_count )
  697.         return LESSTHAN;
  698.         if ( thisp -> arc_count > thatp -> arc_count )
  699.         return GREATERTHAN;
  700.         return EQUALTO;
  701.     }
  702.     }
  703. }
  704.  
  705. int
  706. namecmp( npp1 , npp2 )
  707.     nltype **npp1, **npp2;
  708. {
  709.     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
  710. }
  711.  
  712. printindex()
  713. {
  714.     nltype        **namesortnlp;
  715.     register nltype    *nlp;
  716.     int            index, nnames, todo, i, j;
  717.     char        peterbuffer[20];
  718.  
  719.     /*
  720.      *    Now, sort regular function name alphbetically
  721.      *    to create an index.
  722.      */
  723.     namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
  724.     if ( namesortnlp == (nltype **) 0 ) {
  725.     fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
  726.     }
  727.     for ( index = 0 , nnames = 0 ; index < nname ; index++ ) {
  728.     if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 )
  729.         continue;
  730.     namesortnlp[nnames++] = &nl[index];
  731.     }
  732.     qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp );
  733.     for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) {
  734.     namesortnlp[todo++] = &cyclenl[index];
  735.     }
  736.     printf( "\f\nIndex by function name\n\n" );
  737.     index = ( todo + 2 ) / 3;
  738.     for ( i = 0; i < index ; i++ ) {
  739.     for ( j = i; j < todo ; j += index ) {
  740.         nlp = namesortnlp[ j ];
  741.         if ( nlp -> printflag ) {
  742.         sprintf( peterbuffer , "[%d]" , nlp -> index );
  743.         } else {
  744.         sprintf( peterbuffer , "(%d)" , nlp -> index );
  745.         }
  746.         if ( j < nnames ) {
  747.         printf( "%6.6s " , peterbuffer );
  748.         if (bsd_style_output)
  749.             printf ("%-19.19s" , nlp->name);
  750.         else {
  751.             int size = printnameonly(nlp);
  752.             for ( ; size < 19; size++) putchar(' ');
  753.         }
  754.         } else {
  755.         printf( "%6.6s " , peterbuffer );
  756.         sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno );
  757.         printf( "%-19.19s" , peterbuffer );
  758.         }
  759.     }
  760.     printf( "\n" );
  761.     }
  762.     cfree( namesortnlp );
  763. }
  764.  
  765. PTR
  766. xmalloc (size)
  767.      long size;
  768. {
  769.     PTR val = (PTR) malloc (size);
  770.     if (val == NULL) {
  771.     fprintf (stderr, "virtual memory exhaused\n");
  772.     exit (1);
  773.     }
  774.     return val;
  775. }
  776.  
  777. PTR
  778. xrealloc (oldval, size)
  779.      PTR oldval;
  780.      long size;
  781. {
  782.     PTR val = (PTR) realloc (oldval, size);
  783.     if (val == NULL) {
  784.     fprintf (stderr, "virtual memory exhaused\n");
  785.     exit (1);
  786.     }
  787.     return val;
  788. }
  789.  
  790.